package Client;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.util.Hashtable;

import javax.swing.ImageIcon;

public final class Sprite {
    private static final Color TRANSPARENT_COLOR = new Color(50, 205, 50); // Lime green
    private static final int TRANSPARENT_MARKER_RGB = TRANSPARENT_COLOR.getRGB() | 0xff000000;
    private static Hashtable<Integer, Sprite> spriteCache = new Hashtable<Integer, Sprite>();
    private BufferedImage image;
    private int width;
    private int height;

    /*
     * Transparency thanks to http://www.rgagnon.com/javadetails/java-0265.html
     */
    public Sprite(BufferedImage image) {
        ImageFilter filter = new RGBImageFilter() {
            @Override
            public final int filterRGB(int x, int y, int rgb) {
                if ((rgb | 0xff000000) == TRANSPARENT_MARKER_RGB) {
                    return 0x00ffffff & rgb;
                }
                return rgb;
            }
        };
        ImageProducer ip = new FilteredImageSource(image.getSource(), filter);
        this.image = toBufferedImage(Toolkit.getDefaultToolkit().createImage(ip));
        width = image.getWidth();
        height = image.getHeight();
    }

    public Sprite(int fileId) {
        this("./cache/sprite/" + fileId + ".png");
    }

    public Sprite(String fileName) {
        this(toBufferedImage(new ImageIcon(fileName).getImage()));
    }

    public BufferedImage image() {
        return image;
    }

    public int width() {
        return width;
    }

    public int height() {
        return height;
    }

    public static BufferedImage toBufferedImage(Image image) {
        BufferedImage bImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = bImage.createGraphics();
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return bImage;
    }

    public static BufferedImage resize(BufferedImage image, int width, int height) {
        BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = resizedImage.createGraphics();
        g.setComposite(AlphaComposite.Src);
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.drawImage(image, 0, 0, width, height, null);
        g.dispose();
        return resizedImage;
    }

    public static Sprite getSprite(int id) {
        if (spriteCache.containsKey(id)) {
            return spriteCache.get(id);
        }
        Sprite s = new Sprite(id);
        spriteCache.put(id, s);
        return s;
    }
}